package chapter06._05_Proxy;

import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Random;

/**
 * @Version:
 * @Description: 使用代理类跟踪方法调用
 * @LastDate: 2020/10/4
 */
public class ProxyTest {

    public static void main(String[] args) {
        /*
        * 使用Proxy的newProxyInstance来创建代理对象
        * 需要三个参数 classLoader class[] 一个调用处理器invocation handler
        * 在这里选用系统加载器作为加载器
        * 其中 调用处理器是一个类的对象 一个实现了InvocationHandler接口的类
        * */
        var elements = new Object[1000];
        //给数组填充proxy对象
        for (int i = 0; i < elements.length; i++) {
            Integer value = i + 1;
            var handler = new TraceHandler(value);
            Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
                    new Class[]{Comparable.class}, handler);
            elements[i] = proxy;
        }

        //生成一个随机数
        Integer key = new Random().nextInt(elements.length) + 1;

        //二分查找
        int ans = Arrays.binarySearch(elements, key);
        if (ans >= 0) {
            System.out.println(elements[ans]);
        }
    }
}
/*
* 实现InvocationHandler接口的类
* 这个接口只有一个方法 invoke
* 当代理对象的方法被调用 invoke也一起被调用
* */
class TraceHandler implements InvocationHandler {
    private Object t;


    TraceHandler(Object t) {
        this.t = t;
    }

    /*
     * @Description:
     * @Param method 被调用的方法 args 传入被调用方法的参数
     * @return
     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.print(t);

        System.out.print("." + method.getName() + "(");

        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                System.out.print(args[i]);
                if (i != args.length - 1) System.out.print(", ");
            }
        }

        System.out.println(")");
        //真正调用invoke
        return method.invoke(t, args);
    }
}
